package utils;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * <p>
 * 数据结构与算法-通用 API 工具类
 * </p>
 *
 * @author AJun
 * @since 2020/8/10
 */
@SuppressWarnings("ManualArrayCopy")
public class Tools {

    /**
     * 打印
     *
     * @param obj 对象
     */
    public static void println(Object obj) {
        System.out.println(obj);
    }

    /**
     * 打印
     *
     * @param array 数组对象
     */
    public static void println(Object[] array) {
        for (Object data : array) {
            System.out.printf("%-3s\t", data);
        }
        System.out.println();
    }

    /**
     * 打印 int[] 数组
     *
     * @param array int[] 数组
     */
    public static void println(int[] array) {
        for (int data : array) {
            System.out.printf("%-3d\t", data);
        }
        System.out.println();
    }

    /**
     * 交换数组中的2个元素
     *
     * @param array 数组
     * @param i     第1个索引
     * @param k     第2个索引
     */
    public static void swap(int[] array, int i, int k) {
        if (array == null || array.length == 1) {
            return;
        }
        int temp = array[i];
        array[i] = array[k];
        array[k] = temp;
    }

    /**
     * 交换数组中的2个元素，交换任意类型的数组
     *
     * @param array 数组
     * @param i     第1个索引
     * @param k     第2个索引
     */
    public static <T> void swap(T[] array, int i, int k) {
        if (array == null || array.length == 1) {
            return;
        }
        T temp = array[i];
        array[i] = array[k];
        array[k] = temp;
    }

    /**
     * int[] 数组移位
     *
     * @param arr  int[] 数组
     * @param lOrR true: 左移；false: 右移
     */
    public static void shift(int[] arr, boolean lOrR) {
        if (lOrR) shiftL(arr);
        else shiftR(arr);
    }

    /**
     * int[] 数组左移
     *
     * @param arr int[] 数组
     */
    public static void shiftL(int[] arr) {
        int len = arr.length;
        // 将下标为 0 的元素保存在一个临时的变量中
        int temp = arr[0];

        // 循环向前移位，不包括最后一个元素
        for (int i = 0; i < len - 1; i++) {
            arr[i] = arr[i + 1];
        }

        // 把第一个值放到最后一位
        arr[len - 1] = temp;
    }

    /**
     * int[] 数组右移
     *
     * @param arr int[] 数组
     */
    public static void shiftR(int[] arr) {
        int len = arr.length;
        // 把最后一位保存在临时变量中
        int temp = arr[len - 1];

        // 循环向后移位，不包括第一个元素
        for (int i = arr.length - 1; i >= 1; i--) {
            arr[i] = arr[i - 1];
        }

        // 将最后一位的值放入第一位
        arr[0] = temp;
    }

    /**
     * T[] 数组移位
     *
     * @param arr  T[] 数组
     * @param lOrR true: 左移；false: 右移
     */
    public static <T> void shift(T[] arr, boolean lOrR) {
        if (lOrR) shiftL(arr);
        else shiftR(arr);
    }

    /**
     * T[] 数组左移
     *
     * @param arr T[] 数组
     */
    public static <T> void shiftL(T[] arr) {
        int len = arr.length;
        // 将下标为 0 的元素保存在一个临时的变量中
        T temp = arr[0];

        // 循环向前移位，不包括最后一个元素
        for (int i = 0; i < len - 1; i++) {
            arr[i] = arr[i + 1];
        }

        // 把第一个值放到最后一位
        arr[len - 1] = temp;
    }

    /**
     * T[] 数组右移
     *
     * @param arr T[] 数组
     */
    public static <T> void shiftR(T[] arr) {
        int len = arr.length;
        // 把最后一位保存在临时变量中
        T temp = arr[len - 1];

        // 循环向后移位，不包括第一个元素
        for (int i = arr.length - 1; i >= 1; i--) {
            arr[i] = arr[i - 1];
        }

        // 将最后一位的值放入第一位
        arr[0] = temp;
    }

    /**
     * 测试 value 是否正确
     */
    public static void asserts(boolean value) {
        try {
            if (!value) throw new Exception("测试未通过");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算代码执行时间
     *
     * @param task 任务
     */
    public static void calcTime(Task task) {
        calcTime("", task);
    }

    /**
     * 计算代码执行时间
     *
     * @param title 标题
     * @param task  任务
     */
    public static void calcTime(String title, Task task) {
        if (task == null) return;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
        title = (title == null) ? "" : ("[" + title + "]");
        println(title);
        println("开始 => " + formatter.format(LocalTime.now()));
        long start = System.currentTimeMillis();
        task.execute();
        long end = System.currentTimeMillis();
        println("结束 => " + formatter.format(LocalTime.now()));
        double duration = (end - start) / 1000.0;
        println("耗时 => " + duration + "秒");
        println("---------------------------");
    }

    /**
     * 执行任务的接口
     */
    public interface Task {
        void execute();
    }

}
